package za.org.jcicada.comms.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import za.org.jcicada.comms.IAcceptListener;
import za.org.jcicada.comms.IAcceptor;
import za.org.jcicada.comms.IConnection;

/**
 * Abstract base class for acceptors that keeps a handle to the accept
 * listener and the connected clients.
 */
public abstract class AcceptorBase implements IAcceptor {

    private static final Log logger = LogFactory.getLog(AcceptorBase.class);
    private IAcceptListener acceptListener;
    private List<IConnection> connections = new ArrayList<IConnection>();

    public AcceptorBase(IAcceptListener acceptListener) {
        this.acceptListener = acceptListener;
    }

    @Override
    public synchronized void close() throws IOException {
        for (IConnection client : new ArrayList<IConnection>(connections)) {
            removeQueue(client);
        }
    }

    public synchronized void addQueue(IConnection client) {
    	if (connections.contains(client)) {
    		throw new IllegalStateException(String.format("%s already added to %s", client, this));
    	}
        try {
            acceptListener.onAccept(client);
        } catch (Exception ex) {
            logger.error(String.format("Accept listener %s failed to accept queue %s", acceptListener, client), ex);
        }
        connections.add(client);
    }

    public synchronized void removeQueue(IConnection client) {
    	if (!connections.contains(client)) {
    		throw new IllegalStateException(String.format("%s doesn't contain %s", this, client));
    	}
        try {
            acceptListener.onClose(client);
        } catch (Exception ex) {
            logger.error(String.format("Accept listener %s failed to close queue %s", acceptListener, client), ex);
        }
        connections.remove(client);
    }
    
    @Override
    public IAcceptListener getListener() {
    	return acceptListener;
    }
    
    @Override
    public String toString() {
    	return String.format("%s:%s", getClass().getSimpleName(), getListener().getClass().getSimpleName());
    }

}
